package com.sky.server;

import com.sky.constant.NettyConstant;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * netty服务器业务处理器配置
 * @author Administrator
 */
@Component
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Value("${websocket.url}")
    private String websocketUrl;

    @Resource
    private WebSocketServerHandler webSocketServerHandler;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // Netty自己的http解码器和编码器，报文级别 HTTP请求的解码和编码
        pipeline.addLast(new HttpServerCodec());
        // ChunkedWriteHandler 是用于大数据的分区传输
        // 主要用于处理大数据流，比如一个1G大小的文件如果你直接传输肯定会撑暴jvm内存的;
        // 增加之后就不用考虑这个问题了
        pipeline.addLast(new ChunkedWriteHandler());
        // HttpObjectAggregator 是完全的解析Http消息体请求用的
        // 把多个消息转换为一个单一的完全FullHttpRequest或是FullHttpResponse，
        // 原因是HTTP解码器会在每个HTTP消息中生成多个消息对象HttpRequest/HttpResponse,HttpContent,LastHttpContent
        pipeline.addLast(new HttpObjectAggregator(65536));
        // WebSocket数据压缩
        pipeline.addLast(new WebSocketServerCompressionHandler());
        /**
         * 说明：
         * 1、对应webSocket，它的数据是以帧（frame）的形式传递
         * 2、浏览器请求时 ws://localhost:13001/ws 表示请求的uri
         * 3、核心功能是将http协议升级为ws协议，保持长连接
        */
        pipeline.addLast(new WebSocketServerProtocolHandler(websocketUrl, null, true, 10 * 1024));
        // netty自带的日志记录，按照配置的日志级别进行日志打印
        // pipeline.addLast("logging",new LoggingHandler(LogLevel.INFO));

        // 当连接在60秒内没有接收到消息时，就会触发一个 IdleStateEvent 事件，
        // 此事件被 HeartbeatHandler 的 userEventTriggered 方法处理到
        pipeline.addLast(new IdleStateHandler(NettyConstant.READ_IDLE_TIME_OUT, NettyConstant.WRITE_IDLE_TIME_OUT, NettyConstant.ALL_IDLE_TIME_OUT, TimeUnit.SECONDS));

        // MyServerHandler、TextWebSocketFrameHandler 是自定义逻辑处理器，
        pipeline.addLast(webSocketServerHandler);
    }
}
